﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PServiceBus.WebAPI.DTO;
using PServiceBus.Services.Web;
using System.Threading;
using System.Threading.Tasks;
using System.Net.Http;
using System.Web.Http.Controllers;
using System.Net;
using System.Web.Http;
using PServiceBus.Services.Web.DTO;
using PServiceBus.Services.Gateway.Runtime;
using System.ServiceModel.Channels;
using System.Web.Http.ModelBinding;

namespace PServiceBus.WebAPI.Controllers {

    public partial class ESBController {

        const string POST = "POST", GET = "GET";

        [AcceptVerbs(POST)]
        public HttpResponseMessage CreateSubscriber(NameObject info) {
            if (info == null) throw new ArgumentNullException("info");
            return GetCreateSubscriber(info.name);
        }

       [AcceptVerbs(POST)]
        public HttpResponseMessage ChangeSubscriberDurability(SubscriptionInfo info) {
            MessageBus.ChangeSubscriberDurability(info);
            return EmptyResponse;
        }

       [AcceptVerbs(POST)]
       public string Subscribe(SubscriptionInfo info) {
            MessageBus.Subscribe(info);
            return info.Subscriber;
        }

        [AcceptVerbs(POST)]
       public string Update(SubscriptionInfo info) {
            MessageBus.Update(info);
            return info.Subscriber;
        }

        [AcceptVerbs(POST)]
        public string UnSubscribe(SubscriptionInfo info) {
            MessageBus.UnSubscribe(info);
            EndStreaming(info.Subscriber, info.Transport != null ? info.Transport.Name : info.Topic);
            return info.Subscriber;
        }

        [AcceptVerbs(POST)]
        public HttpResponseMessage AddTransport(SubscriptionInfo info) {
            MessageBus.AddTransport(info);
            return EmptyResponse;
        }

        [AcceptVerbs(POST)]
        public HttpResponseMessage DeleteTransport(SubscriptionInfo info) {
            MessageBus.DeleteTransport(info);
            return EmptyResponse;
        }

        [AcceptVerbs(POST)]
        public Subscriber SelectSubscriber(NameObject info) {
            if (info == null) throw new ArgumentNullException("info");
            return GetSelectSubscriber(info.name);
        }

        [AcceptVerbs(POST)]
        public Topic SelectTopic(NameObject info) {
            if (info == null) throw new ArgumentNullException("info");
            return GetSelectTopic(info.name);
        }

        [AcceptVerbs(POST)]
        public bool Ping() {
            return MessageBus.Ping();
        }

        [AcceptVerbs(POST)]
        public HttpResponseMessage DeleteSubscriber(NameObject info) {
            if (info == null) throw new ArgumentNullException("info");
            return GetDeleteSubscriber(info.name);
        }

        [AcceptVerbs(POST)]
        public HttpResponseMessage DeleteTopic(NameObject info) {
            if (info == null) throw new ArgumentNullException("info");
            return GetDeleteTopic(info.name);
        }

        [AcceptVerbs(POST)]
        public HttpResponseMessage RegisterTopic(TopicInfo info) {
            MessageBus.RegisterTopic(info);
            return EmptyResponse;
        }

        private void IncludeHttpHeaders(Dictionary<string, string> headers) {
            const string includeHttpHeaderKey = "includeHttpHeaders";
            if (String.IsNullOrWhiteSpace(QueryString[includeHttpHeaderKey]))
                return;
            var request = Request;
            headers["PSB-ClientIpAddress"] =
                request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name) ?
                (request.Properties[RemoteEndpointMessageProperty.Name] 
                as RemoteEndpointMessageProperty).Address : string.Empty;
            headers["PSB-HTTPHeaders"] = String.Join(",", request.Headers.Select(x => String.Concat(x.Key, "=", String.Join(",", x.Value))));
            headers["PSB-HTTPUrlReferrer"] = request.Headers.Referrer != null ? request.Headers.Referrer.ToString() : string.Empty;
            headers["PSB-HTTPUserAgent"] = request.Headers.UserAgent.First().Product.Name;
            headers["PSB-HTTPCookies"] = String.Join(";", request.Headers.GetCookies()
                .Select(x => String.Format("name={0}, value={1}, expires={2}, path={3}",
                    String.Join(";", x.Cookies.Select(y => y.Name)), 
                    String.Join(";", x.Cookies.Select(y => y.Value)),
                    x.Expires, x.Path)));
        }

        [AcceptVerbs(POST)]
        public HttpResponseMessage PublishTopic(PublishTopicInfo info) {
            if (info != null) {
                info.Headers = info.Headers ?? new Dictionary<string, string>();
                IncludeHttpHeaders(info.Headers);
            }
            MessageBus.PublishTopic(info);
            return EmptyResponse;
        }

        [AcceptVerbs(POST)]
        public IEnumerable<Topic> GetTopics() {
            return MessageBus.GetTopics();
        }

        [AcceptVerbs(POST)]
        public HttpResponseMessage Disconnect(NameObject info) {
            if (info == null) throw new ArgumentNullException("info");
            return GetDisconnect(info.name);
        }
    }
}
